﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace IWMAG.Core.EnhancedProperties
{
    public static class PropertyManager
    {
        static Dictionary<UniqueIdentifier, PropertyBacker> registrations = new Dictionary<UniqueIdentifier, PropertyBacker>();



        public static PropertyBacker<T> Register<T>(string propName, T defaultValue = default(T), Func<T, T> coerceValueCallback = null, PropertyMetadata metadata = null)
        {
            Contract.Requires(!string.IsNullOrWhiteSpace(propName));
            var ret = new PropertyBacker<T>(defaultValue,coerceValueCallback);
            ret.PropertyName = propName;
            if (metadata == null)
            {
                ret.Metadata = Metadata.Get();
            }
            else
            {
                ret.Metadata = metadata;
            }
           
            registrations.Add(ret.UniqueID, ret);

            return ret;
        }

        static Dictionary<UniqueIdentifier, SortedSet<UniqueIdentifier>> allAffectedProperties = new Dictionary<UniqueIdentifier,SortedSet<UniqueIdentifier>>();
        internal static void RegisterPropertyAffected(UniqueIdentifier objectID, UniqueIdentifier propID)
        {
            SortedSet<UniqueIdentifier> list;
            if (allAffectedProperties.TryGetValue(objectID, out list))
            {
                list.Add(propID);
            }
            else
            {
                list = new SortedSet<UniqueIdentifier>();
                allAffectedProperties.Add(objectID, list);
                list.Add(propID);
            }
        }

        internal static void UnregisterPropertyAffected(UniqueIdentifier objectID, UniqueIdentifier propID)
        {
            SortedSet<UniqueIdentifier> list;
            if (allAffectedProperties.TryGetValue(objectID,out list))
            {
                list.Remove(propID);
            }
        }

        internal static void DisposingObject(UniqueIdentifier objectID)
        {
            SortedSet<UniqueIdentifier> list;
            if (allAffectedProperties.TryGetValue(objectID,out list))
            {
                foreach (var item in list)
                {
                    PropertyBacker pb;
                    if (registrations.TryGetValue(item,out pb))
                    {
                        pb.DisposeObjectReferences(objectID);
                    }
                    else
                    {
                        throw new NotSupportedException("Property not registered with system!!!");
                    }
                }
            }
        }
    }

}
